home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
language
/
clisp_c.zoo
/
defmacro.lsp
< prev
next >
Wrap
Lisp/Scheme
|
1993-06-05
|
29KB
|
616 lines
;;;; File DEFMACRO.LSP
;;; Macro DEFMACRO und einige Hilfsfunktionen für komplizierte Macros.
;;; 1. 9. 1988
;;; Adaptiert an DEFTYPE am 10.6.1989
(in-package "SYSTEM")
;; Import aus CONTROL.Q:
#| (SYSTEM::PARSE-BODY body &optional docstring-allowed env)
expandiert die ersten Formen in der Formenliste body (im Function-
Environment env), entdeckt dabei auftretende Deklarationen (und falls
docstring-allowed=T, auch einen Docstring) und liefert drei Werte:
1. body-rest, die restlichen Formen,
2. declspec-list, eine Liste der aufgetretenen Decl-Specs,
3. docstring, ein aufgetretener Docstring oder NIL.
|#
#| (SYSTEM::KEYWORD-TEST arglist kwlist)
testet, ob arglist (eine paarige Keyword/Value-Liste) nur Keywords
enthält, die auch in der Liste kwlist vorkommen, oder aber ein
Keyword/Value-Paar :ALLOW-OTHER-KEYS mit Value /= NIL enthält.
Wenn nein, wird ein Error ausgelöst.
|#
#| (keyword-test arglist kwlist) überprüft, ob in arglist (eine Liste
von Keyword/Value-Paaren) nur Keywords vorkommen, die in kwlist vorkommen,
oder ein Keyword/Value-Paar mit Keyword = :ALLOW-OTHER-KEYS und Value /= NIL
vorkommt. Sollte dies nicht der Fall sein, wird eine Errormeldung ausgegeben.
(defun keyword-test (arglist kwlist)
(let ((unallowed-arglistr nil)
(allow-other-keys-flag nil))
(do ((arglistr arglist (cddr arglistr)))
((null arglistr))
(if (eq (first arglistr) ':ALLOW-OTHER-KEYS)
(if (second arglistr) (setq allow-other-keys-flag t))
(do ((kw (first arglistr))
(kwlistr kwlist (cdr kwlistr)))
((or (null kwlistr) (eq kw (first kwlistr)))
(if (and (null kwlistr) (null unallowed-arglistr))
(setq unallowed-arglistr arglistr)
) ) ) ))
(unless allow-other-keys-flag
(if unallowed-arglistr
(cerror #+DEUTSCH "Beide werden übergangen."
#+ENGLISH "It will be ignored."
#+FRANCAIS "Ignorer les deux."
#+DEUTSCH "Unzulässiges Keyword ~S mit Wert ~S"
#+ENGLISH "Invalid keyword-value-pair: ~S ~S"
#+FRANCAIS "Mot-clé illégal ~S, valeur ~S"
(first unallowed-arglistr) (second unallowed-arglistr)
) ) )
) )
; Definition in Assembler siehe CONTROL.Q
|#
(defun macro-call-error (macro-form)
(error #+DEUTSCH "Der Macro ~S kann nicht mit ~S Argumenten aufgerufen werden: ~S"
#+ENGLISH "The macro ~S may not be called with ~S arguments"
#+FRANCAIS "Le macro ~S ne peut pas être appelé avec ~S arguments : ~S"
(car macro-form) (1- (length macro-form)) macro-form
) )
(proclaim '(special
%restp ; gibt an, ob &REST/&BODY/&KEY angegeben wurde,
; also ob die Argumentanzahl unbeschränkt ist.
%min-args ; gibt die Anzahl der notwendigen Argumente an
%arg-count ; gibt die Anzahl der Einzelargumente an
; (notwendige und optionale Argumente, zusammengezählt)
%let-list ; umgedrehte Liste der Bindungen, die mit LET* zu machen sind
%keyword-tests ; Liste der KEYWORD-TEST - Aufrufe, die einzubinden sind
%default-form ; Default-Form für optionale und Keyword-Argumente,
; bei denen keine Default-Form angegeben ist.
; =NIL normalerweise, = (QUOTE *) für DEFTYPE.
) )
#|
(ANALYZE1 lambdalist accessexp name wholevar)
analysiert eine Macro-Lambdaliste (ohne &ENVIRONMENT). accessexp ist der
Ausdruck, der die Argumente liefert, die mit dieser Lambdaliste zu matchen
sind.
(ANALYZE-REST lambdalistr restexp name)
analysiert den Teil einer Macro-Lambdaliste, der nach &REST/&BODY kommt.
restexp ist der Ausdruck, der die Argumente liefert, die mit diesem
Listenrest zu matchen sind.
(ANALYZE-KEY lambdalistr restvar name)
analysiert den Teil einer Macro-Lambdaliste, der nach &KEY kommt.
restvar ist das Symbol, das die restlichen Argumente enthalten wird.
(ANALYZE-AUX lambdalistr name)
analysiert den Teil einer Macro-Lambdaliste, der nach &AUX kommt.
(REMOVE-ENV-ARG lambdalist name)
entfernt das Paar &ENVIRONMENT/Symbol aus einer Macro-Lambdaliste,
liefert zwei Werte: die verkürzte Lambdaliste und das als Environment zu
verwendende Symbol (oder die Lambdaliste selbst und NIL, falls &ENVIRONMENT
nicht auftritt).
(MAKE-LENGTH-TEST symbol)
kreiert aus %restp, %min-args, %arg-count eine Testform, die bei Auswertung
anzeigt, ob der Inhalt der Variablen symbol als Aufruferform zum Macro
dienen kann.
(MAKE-MACRO-EXPANSION macrodef)
liefert zu einer Macrodefinition macrodef = (name lambdalist . body)
1. den Macro-Expander als Programmtext (FUNCTION ... (LAMBDA ...)),
2. name, ein Symbol,
3. lambdalist,
4. docstring (oder NIL, wenn keiner da).
|#
(%proclaim-constant 'macro-missing-value (list 'macro-missing-value))
; einmaliges Objekt
(%putd 'analyze-aux
(function analyze-aux
(lambda (lambdalistr name)
(do ((listr lambdalistr (cdr listr)))
((atom listr)
(if listr
(cerror #+DEUTSCH "Der Teil danach wird ignoriert."
#+ENGLISH "The rest of the lambda list will be ignored."
#+FRANCAIS "Ignorer ce qui suit."
#+DEUTSCH "Die Lambdaliste des Macros ~S enthält einen Punkt nach &AUX."
#+ENGLISH "The lambda list of macro ~S contains a dot after &AUX."
#+FRANCAIS "La liste lambda du macro ~S contient un point après &AUX."
name
)) )
(cond ((symbolp (car listr)) (setq %let-list (cons `(,(car listr) nil) %let-list)))
((atom (car listr))
(error #+DEUTSCH "Im Macro ~S ist als &AUX-Variable nicht verwendbar: ~S"
#+ENGLISH "in macro ~S: ~S may not be used as &AUX variable."
#+FRANCAIS "Dans le macro ~S, l'utilisation de ~S n'est pas possible comme variable &AUX."
name (car listr)
))
(t (setq %let-list
(cons `(,(caar listr) ,(cadar listr)) %let-list)
) ) ) ) ) )
)
(%putd 'analyze-key
(function analyze-key
(lambda (lambdalistr restvar name &aux (otherkeysforbidden t) (kwlist nil))
(do ((listr lambdalistr (cdr listr))
(next)
(kw)
(svar)
(g))
((atom listr)
(if listr
(cerror #+DEUTSCH "Der Teil danach wird ignoriert."
#+ENGLISH "The rest of the lambda list will be ignored."
#+FRANCAIS "Ignorer ce qui suit."
#+DEUTSCH "Die Lambdaliste des Macros ~S enthält einen Punkt nach &KEY."
#+ENGLISH "The lambda list of macro ~S contains a dot after &KEY."
#+FRANCAIS "La liste lambda du macro ~S contient un point après &KEY."
name
)) )
(setq next (car listr))
(cond ((eq next '&ALLOW-OTHER-KEYS) (setq otherkeysforbidden nil))
((eq next '&AUX) (return-from nil (analyze-aux (cdr listr) name)))
((or (eq next '&ENVIRONMENT) (eq next '&WHOLE) (eq next '&OPTIONAL)
(eq next '&REST) (eq next '&BODY) (eq next '&KEY)
)
(cerror #+DEUTSCH "Es wird ignoriert."
#+ENGLISH "It will be ignored."
#+FRANCAIS "Ignorer ce qui suit."
#+DEUTSCH "Die Lambdaliste des Macros ~S enthält ein ~S an falscher Stelle."
#+ENGLISH "The lambda list of macro ~S contains a badly placed ~S."
#+FRANCAIS "La liste lambda du macro ~S contient un ~S mal placé."
name next
))
(t
(if %default-form
(cond ((symbolp next) (setq next (list next %default-form)))
((and (consp next) (eql (length next) 1))
(setq n